<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>探测雷达</title>
  <link rel="stylesheet" href="/static/css/bootstrap.min.css">
  <link rel="stylesheet" href="/static/css/bbfont.css">
  <link rel="stylesheet" href="/static/css/style.css">
  <link rel="stylesheet" href="qv.css">
  <script src="/static/js/echarts.4.9.js"></script>
  <style>
    :root {
      --box-color: #ccc;
    }

    .CCC > * {
      height: 24px !important;
      padding: 1px 5px;
      margin: 0;
      border: none;
      outline: none;
      vertical-align: top;
    }

    .items > div {
      border: solid 1px var(--box-color);
    }

    .realtime > div > div {
      position: relative;
    }

    .realtime > div > div > .chart {
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      width: 100%;
    }

    #viewer .card-header {
      padding: 2px 12px;
      font-size: 15px;
    }

    #viewer .card-header::before {
      font-size: 14px;
      position: absolute;
      top: 6px;
      left: 5px;
    }

  </style>
</head>
<body id="viewer" class="M1">
<div id="CCC" style="padding: 4px 6px;">
  <button class="btn btn-primary btn-sm disactive-btn" onclick="main.realtime()" id="realtime">实时</button>
  <button class="btn btn-primary btn-sm mx-1" id="history" onclick="main.history()">历史</button>
  日期:
  <input id="day" type="date" value="" disabled>
  任务:
  <select id="task" class="sele-comp" disabled>
  </select>
  工作模式:
  <select id="modes" class="sele-comp"></select>
  <label id="frm_max" hidden></label>
  <input id="frm_input" oninput="this.nextElementSibling.value=this.value" style="width: 60px" maxlength="4" hidden>
  <input oninput="this.previousElementSibling.value=this.value" style="width: calc(100vw - 1300px);padding:0;"
         id="frm_range" type="range" min="0" max="0" value="0" step="1" hidden>
  <button id="frm_img_table" class="btn btn-primary btn-sm" style="display: none">LI</button>
  <label class="history">
    抽样间隔: <input type="number" style="max-width: 120px">
    <button class="btn btn-primary btn-sm">抽样</button>
    <button class="btn btn-primary btn-sm">累加</button>
  </label>

</div>
<div style="height: calc(100vh - 37px);background: #fff" class="d-flex flex-row">
  <div class="realtime flex-grow-1 d-flex flex-column position-relative">
    <div class="w-100 d-grid items" style="grid-template-columns: 40% 60%;gap:2px">
      <div class="card-header" id="ltitle">低频</div>
      <div class="card-header">高频</div>
    </div>
    <div class="w-100 flex-grow-1 d-grid position-relative items" style="grid-template-columns: 40% 60%; gap: 2px">
      <div>
        <div class="chart"></div>
      </div>
      <div>
        <div class="chart"></div>
      </div>
      <div>
        <div class="chart"></div>
      </div>
      <div>
        <div class="chart"></div>
      </div>
      <div>
        <div class="chart"></div>
      </div>
      <div>
        <div class="chart"></div>
      </div>
      <div>
        <div class="chart"></div>
      </div>
      <div>
        <div class="chart"></div>
      </div>

    </div>
  </div>
  <div class="d-flex flex-column position-relative" style="width: 400px; border-left: solid 1px var(--box-color);">
    <div class="card-header">帧信息</div>
    <div class="flex-grow-1 position-relative">
      <div class="h-100 w-100 position-absolute overflow-auto">
        <table class="table table-sm table-bordered table-hover small">
          <tbody class="info" id="params"></tbody>
        </table>
      </div>

    </div>
  </div>
</div>
<script src="/static/js/jquery-3.6.0.min.js"></script>
<script src="/static/js/xtool.js?12"></script>

<script src="acsr.js"></script>
<script src="qv.js"></script>
<script>
  var toPrecision2 = (v)=>{ return Math.round(v*100)/100 }
  // todo oa data postion :/home/shk/_root/DASWORK
  function genFreqs(freqType, stepV) {
    // unit MHz
    const FREQ_META = {
      0: {
        bw: 40,
        stepUnitV: 0.01,
        f0: 150,
        splitNumber: 8
      }, 1: {
        bw: 1200,
        stepUnitV: 0.02,
        f0: 900,
        splitNumber: 16
      }
    }
    meta = FREQ_META[freqType]
    freqStep = stepV * meta.stepUnitV
    pulseNum = meta.bw / freqStep + 1
    fc = (pulseNum - 1) / 2 + 1
    freqs = Array.from({length: pulseNum}, (_, i) => {
      return toPrecision2(meta.f0 + (i + 1 - fc) * freqStep)
    })
    return freqs
  }

  const MODE_META = {
    35: {n: '噪声测量模式1'},
    36: {n: '噪声测量模式2'},
    37: {n: '低频测量模式1'},
    38: {n: '高频测量模式1'},
    39: {n: '低频测量模式2'},
    40: {n: '高频测量模式2'},
    41: {n: '定标模式'},
    42: {n: '交替测量模式1'},
    43: {n: '交替测量模式2'}
  }


  class RealView {
    constructor(p) {
      this.p = p
      this.Lx = genFreqs(0, 20)
      this.Hx = genFreqs(1, 10)
      this.LIndex3X = Array.from({length: this.Lx.length}, (_, i) => i + 1)
      this.HIndex3X = Array.from({length: this.Hx.length}, (_, i) => i + 1)
      this.LZoomId = 0;
      this.HZoomId = 1;

      this.chart_meta = [
        {n: '实部', xunit: '频率(MHz)', yunit: '', k: 'real'},
        {n: '幅度', xunit: '频率(MHz)', yunit: '', k: 'amp'},
        {n: '相位', xunit: '频率(MHz)', yunit: '(°)', k: 'pha'},
        {n: '脉压', xunit: '距离(m)', yunit: '(dB)', k: 'sample'}
      ]
      this.initCharts()
      this.$info = $$('.info')
      window.onresize = this.resize.bind(this)
    }

    initCharts() {
      let chart_eles = Array.from(document.querySelectorAll('.realtime > div >div> .chart'));
      let L_eles = chart_eles.filter((ele, i) => i % 2 == 0)
      let H_eles = chart_eles.filter((ele, i) => i % 2 == 1)
      this.L_charts = L_eles.map((v, i) => echarts.init(v))
      this.H_charts = H_eles.map((v, i) => echarts.init(v))
      this.L_charts.forEach(v => v.on('datazoom', this.zooms.bind(this)))
      this.H_charts.forEach(v => v.on('datazoom', this.zooms.bind(this)))
    }

    zooms(e) {
      if (e.batch === undefined) return;
      let b = e.batch[0]
      let zoomData = {type: "dataZoom", dataZoomIndex: 0, start: b.start, end: b.end};
      if (b.dataZoomId == this.LZoomId) this.L_charts.forEach(v => v.dispatchAction(zoomData))
      if (b.dataZoomId == this.HZoomId) this.H_charts.forEach(v => v.dispatchAction(zoomData))
    }

    series(prefix, d, xaxe) {
      if (!d) return []
      let namefmt = (i) => {
        if (d.length > 1) return prefix ? (prefix + '_' + i) : '组_' + i
        return (prefix || '')
      }
      return d.map((v, i) => {
        return {
          name: namefmt(i), type: 'line', showSymbol: false, symbol: 'none',
          lineStyle: {width: 1.5, opacity: 0.75}, data: v.map((v, i) => [xaxe[i], v])
        }
      })

    }

    option(meta, xaxe, zoomId, series) {
      return {
        animation: false,
        tooltip: {
          trigger: 'axis', confine: true, formatter: (params) => {
            let p = params[0]
            let index = p.dataIndex
            let html = "频率: " + p.axisValue + "</br>";
            let charts = []
            if (p.seriesName == undefined || p.seriesName == '' || p.seriesName.indexOf('组') != -1) {
              charts = this.H_charts
            } else {
              charts = this.L_charts
            }
            let opts = charts.map((c, i) => {
              let opt = c.getOption()
              let ss = opt.series.map(s => {
                return opt.title[0].text + " " + s.name + ": " + s.data[index]
              })
              // if (i == 3) ss.push(opt.xAxis[0].name + " : " + opt.series[0].data[index][0])
              return ss.join('</br>')
            }).join('</br>')
            html = html + opts
            return html
          }
        },
        color: ['#0449ad', '#af0202', '#098a09',
          '#5b02ad', '#b75b02', '#72706f', '#8c6402'],
        legend: {top: 5, right: 30},
        dataZoom: [{id: zoomId, type: 'inside'}],
        grid: {top: 40, left: 60, bottom: 50, right: 30},
        title: {
          text: meta.n + meta.yunit,
          textStyle: {fontSize: 14, fontWeight: 400}, padding: [10, 10],
        },
        xAxis: {
          type: 'value', name: meta.xunit,
           // min: xaxe[0], max: xaxe[xaxe.length - 1],
          nameGap: 30, nameLocation: 'middle',
          scale: true
        },
        yAxis: {type: 'value'},
        series: series
      }
    }

    resize() {
      this.L_charts.map(v => v.resize());
      this.H_charts.map(v => v.resize());
    }

    reset() {
      this.L_charts.forEach(c => c.clear())
      this.H_charts.forEach(c => c.clear())
      this.$info.innerHTML = ''
    }

    render(task_path, d) {
      this.renderInfo(d)
      this.renderCharts(task_path, d)
    }

    renderInfo(d) {
      let dinfo = d.info
     /* let info = Params.map((e, i) => {
        return `<tr><th>${e.n}${e.unit ? '(' + e.unit + ')' : ''}</th><td>${e.v ? e.v(dinfo[e.k]) : dinfo[e.k]}</td></tr>`;
      }).join('');*/
      this.p.params(d)
    }

    async renderCharts(task_path, d) {
      if (this._loading) return
      this._loading = true
      try {
        let resp = await $api(`omsp.acsr.rt?f=${task_path}&offset=${d.frm[0]}&L=${d.frm[1]}&H=${d.frm[2]}`)
        let lastfrm_info = this.p.cur_frame.info
        this.L_charts.forEach((c, i) => {
          c.clear()
          let meta = this.chart_meta[i]
          if (resp.l_v[meta.k].length == 0) return
          let xAxisV = this.Lx
          let lv_values = resp.l_v[meta.k]
          if (i == 3) {
            let v_length = lv_values[0].length
            // calc： m * (1/(步进频率*点数)) * (3e8/2)， m 为对应的点数，m ∈[0, (点数-1)] ,因为单位是kHz，所以要 步进数要在原基础上*1000 ，低频当量10
            xAxisV = this.LIndex3X = Array.from({length: v_length}, (_, i) => {return toPrecision2(1.5e4*i*1/(lastfrm_info.low_freq*v_length))})
          }
          let v = this.series('V', lv_values, xAxisV)
          let h = this.series('H', resp.l_h[meta.k], xAxisV)

          c.setOption(this.option(meta, xAxisV, this.LZoomId, [...v, ...h]))
        })
        this.H_charts.forEach((c, i) => {
          c.clear()
          let meta = this.chart_meta[i]
          if (resp.h_a[meta.k].length == 0) return
          let xAxisV = this.Hx
          let lv_values = resp.h_a[meta.k]
          if (i == 3) {
            let v_length = lv_values[0].length
            // 高频当量 20
            xAxisV = this.HIndex3X = Array.from({length: v_length}, (_, i) => {return toPrecision2(7500*i*1/(lastfrm_info.high_freq*v_length))})
          }
          let v = this.series(undefined, lv_values, xAxisV)
          c.setOption(this.option(meta, xAxisV, this.HZoomId, v))
        })
      } finally {
        this._loading = false
      }


    }
  }

  class XPage extends Realtime {
    constructor() {
      super('ACSR', $STATION,Params)
      this.$modes = $$('#modes')
      this.renderMode()
      this.realView = new RealView(this)

    }

    newtask(d) {
      super.newtask(d);
      // this.load_task()
      // this.load_frames()
    }

    realtime() {
      this.$task.innerHTML = ''
      this.$task.value = this.cur_task = ''
      this.realView.reset()
      super.realtime();
    }

    newframe(d) {
      super.newframe(d);
      this.renderMode()
      // if (d.mode == 35 || d.mode == 36) return d
      this.showFrame(d)
      return d
    }

    showFrame(d) {
      this.realView.render(this.cur_task, d)
    }

    renderMode() {
      let st = {};
      let selected = this.$modes.value
      this.frames_ori.forEach(v => {
        st[v.mode] = 1 + (st[v.mode] || 0)
      })
      let opts = '<option value="">不限</option>'
      this.$modes.innerHTML = opts.concat(Object.keys(MODE_META).map(v => {
        return `<option value="${v}">${MODE_META[v].n}  ${v ? (st[v] ? '：'.concat(st[v]) : '：0') : ''}</option>`
      }).join(''));
      this.$modes.value = selected
    }

    history() {
      window.location.href = `ACSR_H.html?t=${this.$task.value}`
    }
  }

  var main = new XPage()
  main.realtime()
</script>
</body>
</html>